package com.zhx.demo.aop;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * ControllerAOP拦截
 *
 * @author zhx
 * @create 2017-10-24 11:33
 **/


@Component
@Aspect
public class ControllerAop {
    private  final static Logger logger = LoggerFactory.getLogger(ControllerAop.class);

    // 一分钟，即1000ms
    private static final long ONE_MINUTE = 150;

    @Pointcut("execution(* com.zhx.demo.web.controller..*.*(..))")
    public void executeController(){

    }

    /**
     * 统计方法执行耗时Around环绕通知
     * @param joinPoint
     * @return
     */
    @Around("executeController()")
    public Object timeAround(ProceedingJoinPoint joinPoint) {
        // 定义返回对象、得到方法需要的参数
        Object obj = null;
        Object[] args = joinPoint.getArgs();
        long startTime = System.currentTimeMillis();

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) attributes.getRequest();

        //用的最多 通知的签名
        Signature signature = joinPoint.getSignature();

        logger.info("-----收到来自IP:"+request.getRemoteAddr()+"的"+request.getMethod()+"请求! ");

        logger.info("-----请求调用:"+signature.getDeclaringTypeName()+"."+signature.getName()+"方法!");
        logger.info("-----请求的参数为:"+   joinPoint.getArgs());
        logger.info("-----请求的链接为: " +request.getRequestURI());

        try {
            obj = joinPoint.proceed(joinPoint.getArgs());
        } catch (Throwable e) {
            logger.error("方法出错 : + {}", e.getMessage());
        }

        // 获取执行的方法名
        long endTime = System.currentTimeMillis();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        // 打印耗时的信息
        this.printExecTime(methodName, startTime, endTime);

        logger.info("-----返回结果为 : {}", JSON.toJSON(obj));

        return obj;
    }

    /**
     * 打印方法执行耗时的信息，如果超过了一定的时间，才打印
     * @param methodName
     * @param startTime
     * @param endTime
     */
    private void printExecTime(String methodName, long startTime, long endTime) {
        long diffTime = endTime - startTime;
        logger.info("-----" + methodName + " 方法执行耗时：" + diffTime + " ms");
    }

}
